package org.eden.heartbeat.client;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.eden.heartbeat.api.configuration.ApplicationConfiguration;
import org.eden.heartbeat.api.exception.JMXException;
import org.eden.heartbeat.client.exception.UnsupportedArgumentException;
import org.eden.heartbeat.api.jmx.HeartbeatJMXService;
import org.eden.heartbeat.client.model.ArgumentOption;
import org.eden.heartbeat.client.utils.TimeUtils;
import org.eden.heartbeat.api.jmx.HeartbeatCoreMBean;
import org.eden.heartbeat.api.jmx.HeartbeatStatisticsMBean;
import org.eden.heartbeat.api.utils.HeartbeatStringUtils;

import java.text.MessageFormat;
import java.util.Arrays;

/**
 * HeartbeatMain class to communicate with the monitor core while it is running.
 *
 * @author trsimoes
 * @version $Revision:$
 */
public class HeartbeatConsole {

    private static Log LOG = LogFactory.getLog(HeartbeatConsole.class);

    private HeartbeatJMXService heartbeatJMXService = HeartbeatJMXService.getInstance();

    public void execute(String[] args) {
        try {
            if (LOG.isInfoEnabled()) {
                LOG.info("Heartbeat console started");
            }

            // parse command line arguments
            ArgumentOption argumentOption = getArgumentOption(args);

            // load configurations
            ApplicationConfiguration.loadConfigurations();

            // start the jmx service
            this.heartbeatJMXService.start();

            if (LOG.isInfoEnabled()) {
                LOG.info(MessageFormat.format("Invoking {0} method", argumentOption));
            }
            HeartbeatCoreMBean coreProxy;
            HeartbeatStatisticsMBean statisticsProxy;
            switch (argumentOption) {
                case STOP:
                    coreProxy = this.heartbeatJMXService.getHeartbeatCoreProxy();
                    coreProxy.stop();
                    break;
                case RELOAD_CONFIGURATIONS:
                    coreProxy = this.heartbeatJMXService.getHeartbeatCoreProxy();
                    coreProxy.reload();
                    break;
                case GET_TODAY_OFFLINE_TIME:
                    statisticsProxy = this.heartbeatJMXService.getHeartbeatStatisticsProxy();
                    long offlineTime = statisticsProxy.getTodayOfflineTime();
                    String offlineTimeString = TimeUtils.convertToReadableTime(offlineTime);
                    if (LOG.isInfoEnabled()) {
                        LOG.info("OFFLINE TIME IS: " + offlineTimeString);
                    }

                    int numberOfOfflinePeriods = statisticsProxy.getNumberOfOfflinePeriodsToday();
                    if (LOG.isInfoEnabled()) {
                        LOG.info("NUMBER OF OFFLINE PERIODS: " + numberOfOfflinePeriods);
                    }
                    break;
            }
        } catch (Exception e) {
            if (LOG.isErrorEnabled()) {
                LOG.error("Error running HeartbeatConsole", e);
            }
        } finally {
            try {
                // clean up and exit
                this.heartbeatJMXService.close();

                if (LOG.isInfoEnabled()) {
                    LOG.info("Heartbeat console terminated");
                }

            } catch (JMXException e) {
                if (LOG.isErrorEnabled()) {
                    LOG.error("Error closing the JMX service before shutting down the console.", e);
                }
            }
        }
    }

    private ArgumentOption getArgumentOption(String[] args) throws UnsupportedArgumentException {

        if (args == null) {
            if (LOG.isErrorEnabled()) {
                LOG.error(MessageFormat.format("No argument was specified. Available options are {1}.",
                        Arrays.toString(ArgumentOption.values())));
            }
            throw new UnsupportedArgumentException();
        } else if (args.length > 1) {
            if (LOG.isErrorEnabled()) {
                LOG.error(MessageFormat.format("More than one argument was specified. Available options are {1}.",
                        Arrays.toString(ArgumentOption.values())));
            }
            throw new UnsupportedArgumentException();
        }

        String argumentOptionValue =args[0];
        if (HeartbeatStringUtils.isNullOrEmpty(argumentOptionValue)) {
            if (LOG.isErrorEnabled()) {
                LOG.error(MessageFormat.format("No argument was specified. Available options are {1}.",
                        Arrays.toString(ArgumentOption.values())));
            }
            throw new UnsupportedArgumentException();
        }

        ArgumentOption argumentOption = ArgumentOption.fromValue(argumentOptionValue);

        if (argumentOption == null) {
            if (LOG.isInfoEnabled()) {
                LOG.info(MessageFormat.format("Argument option [{0}] not recognized. Available options are {1}.",
                        argumentOptionValue, Arrays.toString(ArgumentOption.values())));
            }
            throw new UnsupportedArgumentException();
        }

        return argumentOption;
    }

    public static void main(String[] args) {
        HeartbeatConsole console = new HeartbeatConsole();
        console.execute(args);
    }
}